using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using FriendsNearby.Services.Entities;
using InSTEDD.Labs.Geo;
using FriendsNearby.Services.Tests.Mocks;
using FriendsNearby.Services.Facebook;
using Facebook.Service;

namespace FriendsNearby.Services.Tests
{
	[TestFixture]
	public class PeopleNearbyServiceFixture
	{
		PeopleNearbyService peopleNearbyService;
		MockLocationService locationService;
		MockSocialNetworkService socialNetworkService;
		MockUsersService usersService;

		[SetUp]
		public void SetUp()
		{
			ServiceProvider serviceProvider = new ServiceProvider();

			locationService = new MockLocationService();
			socialNetworkService = new MockSocialNetworkService();
			usersService = new MockUsersService();
			peopleNearbyService = new PeopleNearbyService(serviceProvider);

			serviceProvider.AddService(typeof(ILocationService), locationService);
			serviceProvider.AddService(typeof(ISocialNetworkService), socialNetworkService);
			serviceProvider.AddService(typeof(IUsersService), usersService);
			serviceProvider.AddService(typeof(IPeopleNearbyService), peopleNearbyService);
		}

		[Test]
		public void MyFriendsAreQuery()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>("B1", "B2", "B3");
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>();
			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 1) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 2) },
				"B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0, 3) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.FriendsAndTheirFriends },
				"B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody }
			);

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetPeopleNearby("me"));

			Assert.IsTrue(socialNetworkService.GetFriends_Called);
			Assert.AreEqual("me", socialNetworkService.GetFriends_UserId);
		}

		[Test]
		public void MyFriendsWithVisibiltyFriendsAndTheirFriendsAreShown()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>("B1", "B2", "B3");
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>();

			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 1) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 2) },
				"B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0, 3) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.FriendsAndTheirFriends },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.FriendsAndTheirFriends },
				"B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.FriendsAndTheirFriends }
			);

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetPeopleNearby("me"));

			Assert.AreEqual(3, persons.Count);
			Assert.IsFalse(Utils.GetPersonNearby(persons, "B1").IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, "B2").IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, "B3").IsHidden);

			Assert.AreEqual(0, Utils.GetPersonNearby(persons, "B1").Location.Lat);
			Assert.AreEqual(1, Utils.GetPersonNearby(persons, "B1").Location.Long);

			Assert.AreEqual(PersonNearbyRelation.Friend, Utils.GetPersonNearby(persons, "B1").Relation);
		}

		[Test]
		public void MyFriendsWithVisibiltyOnlyFriendsAreShown()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>("B1", "B2", "B3");
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>();

			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 1) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 2) },
				"B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0, 3) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends },
				"B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends }
			);

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetPeopleNearby("me"));

			Assert.AreEqual(3, persons.Count);
			Assert.IsFalse(Utils.GetPersonNearby(persons, "B1").IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, "B2").IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, "B3").IsHidden);

			Assert.AreEqual(0, Utils.GetPersonNearby(persons, "B1").Location.Lat);
			Assert.AreEqual(1, Utils.GetPersonNearby(persons, "B1").Location.Long);
		}

		[Test]
		public void MyFriendsWithVisibiltyNobodyAreNotShown()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>("B1", "B2", "B3");
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>();

			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 1) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 2) },
				"B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0, 3) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody },
				"B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody }
			);

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetPeopleNearby("me"));

			Assert.AreEqual(0, persons.Count);
		}

		[Test]
		public void FriendsOfMyFriendsAreQuery()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>();
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>("C1", "C2", "C3");
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>();

			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 1) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 2) },
				"B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0, 3) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.FriendsAndTheirFriends },
				"B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody }
			);

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetPeopleNearby("me"));

			Assert.IsTrue(socialNetworkService.GetFriendsOfFriends_Called);
			Assert.AreEqual("me", socialNetworkService.GetFriendsOfFriends_UserId);
		}

		[Test]
		public void FriendsOfMyFriendsWithVisibiltyFriendsAndTheirFriendsAreShown()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>();
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>("B1", "B2", "B3");

			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 1) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 2) },
				"B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0, 3) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.FriendsAndTheirFriends },
				"B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.FriendsAndTheirFriends }
			);

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetPeopleNearby("me"));

			Assert.AreEqual(3, persons.Count);
			Assert.IsFalse(Utils.GetPersonNearby(persons, "B1").IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, "B2").IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, "B3").IsHidden);

			Assert.AreEqual(0, Utils.GetPersonNearby(persons, "B1").Location.Lat);
			Assert.AreEqual(1, Utils.GetPersonNearby(persons, "B1").Location.Long);

			Assert.AreEqual(PersonNearbyRelation.FriendOfAFriend, Utils.GetPersonNearby(persons, "B1").Relation);
		}

		[Test]
		public void FriendsOfMyFriendsWithVisibiltyOnlyFriendsAreShownHidden()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>();
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>("B1", "B2", "B3");

			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 1) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 2) },
				"B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0, 3) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends },
				"B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends }
			);

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetPeopleNearby("me"));

			Assert.AreEqual(3, persons.Count);
			Assert.IsTrue(Utils.GetPersonNearby(persons, "B1").IsHidden);
			Assert.AreEqual("Unkown 1", Utils.GetPersonNearby(persons, "B1").DisplayName);
			Assert.IsTrue(Utils.GetPersonNearby(persons, "B2").IsHidden);
			Assert.AreEqual("Unkown 2", Utils.GetPersonNearby(persons, "B2").DisplayName);
			Assert.IsTrue(Utils.GetPersonNearby(persons, "B3").IsHidden);
			Assert.AreEqual("Unkown 3", Utils.GetPersonNearby(persons, "B3").DisplayName);

			Assert.AreEqual(0, Utils.GetPersonNearby(persons, "B1").Location.Lat);
			Assert.AreEqual(1, Utils.GetPersonNearby(persons, "B1").Location.Long);
		}

		[Test]
		public void FriendsOfMyFriendsWithVisibiltyNobodyAreNotShown()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>();
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>("C1", "C2", "C3");

			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 1) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 2) },
				"B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0, 3) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody },
				"B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody }
			);

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetPeopleNearby("me"));

			Assert.AreEqual(0, persons.Count);
		}

		[Test]
		public void MyFriendsAreCountedAndTheNearestDistanceIsShown()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>("B1", "B2", "B3");
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>();

			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 1) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 2) },
				"B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0, 3) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone }
			);

			int count;
			double? nearestDistance;
			peopleNearbyService.GetPeopleNearbySummary("me", out count, out nearestDistance);

			Assert.AreEqual(count, 3);
			Assert.AreEqual(nearestDistance, LatLong.DistanceInKm(new LatLong(0, 1), new LatLong(0, 0)));
		}		

		[Test]
		public void MyFriendsAreShownNoMatterIfTheyAreInMyNearby()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>("B1", "B2", "B3");
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>();

			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 1) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 2) },
				"B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0, 3) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone }
			);

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetAllFriends("me"));

			Assert.AreEqual(3, persons.Count);
		}

		[Test]
		public void MyFriendsAreShownIffTheyAreInMyNearby()
		{
			socialNetworkService.GetFriends_Expected =
				Utils.List<string>("B1", "B2");
			socialNetworkService.GetFriendsOfFriends_Expected =
				Utils.List<string>();

			locationService.CurrentLocations = Utils.Map<string, UserInfo>(
				"me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
				"B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 2) },
				"B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 1) }
			);
			usersService.Preferences = Utils.Map<string, UserPreference>(
				"me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = 112, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
				"B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone }
			);

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetPeopleNearby("me"));
			Assert.AreEqual(1, persons.Count);
		}

        [Test]
        public void ShouldGetListOfFriendsWithoutDistanceIfMyLocationIsNotKnown()
        {
            socialNetworkService.GetFriends_Expected =
                Utils.List<string>("B1", "B2");
            socialNetworkService.GetFriendsOfFriends_Expected =
                Utils.List<string>();

            locationService.CurrentLocations = Utils.Map<string, UserInfo>(
                "me", new UserInfo { FacebookUserId = "me", Location = null },
                "B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 2) },
                "B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 1) }
            );
            usersService.Preferences = Utils.Map<string, UserPreference>(
                "me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = 112, VisibilityLevel = (int)VisibilityLevel.Everyone },
                "B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
                "B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone }
            );

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetAllFriends("me"));
            Assert.AreEqual(2, persons.Count);
            Assert.IsNull(persons[0].Distance);
            Assert.IsNull(persons[1].Distance);
        }

        [Test]
        public void UnkownAreEnumeratedFromMyLocationAndLexialorderOfUserId()
        {
            socialNetworkService.GetFriends_Expected =
                Utils.List<string>();
            socialNetworkService.GetFriendsOfFriends_Expected =
                Utils.List<string>("B1", "B2", "B3");

            locationService.CurrentLocations = Utils.Map<string, UserInfo>(
                "me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
                "B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(1, 1) },
                "B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(1, 1) },                
                "B3", new UserInfo { FacebookUserId = "B3", Location = new LatLong(0.5, 0.5) }
            );
            usersService.Preferences = Utils.Map<string, UserPreference>(
                "me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
                "B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends },
                "B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends },
                "B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends }
            );

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetPeopleNearby("me"));

            Assert.AreEqual(3, persons.Count);
            Assert.AreEqual("B3", persons[0].FacebookUserID);
            Assert.AreEqual("Unkown 1", persons[0].DisplayName);
            Assert.AreEqual("B1", persons[1].FacebookUserID);
            Assert.AreEqual("Unkown 2", persons[1].DisplayName);
            Assert.AreEqual("B2", persons[2].FacebookUserID);
            Assert.AreEqual("Unkown 3", persons[2].DisplayName);

        }

        [Test]
        public void ShouldGetListAllPeople()
        {
            socialNetworkService.GetFriends_Expected =
                Utils.List<string>("B1", "B2");
            socialNetworkService.GetFriendsOfFriends_Expected =
                Utils.List<string>("C1");

            locationService.CurrentLocations = Utils.Map<string, UserInfo>(
                "me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
                "B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 2) },
                "B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 1) },
                "C1", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 3) }
            );

            usersService.Preferences = Utils.Map<string, UserPreference>(
                "me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = 0, VisibilityLevel = (int)VisibilityLevel.Everyone },
                "B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
                "B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
                "B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone }
            );

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetAllPeople("me"));
            Assert.AreEqual(3, persons.Count);
        }

        [Test]
        public void ShouldGetListAllPeopleReturnsUserInfosWithLastUpdatedTime()
        {
            socialNetworkService.GetFriends_Expected =
                Utils.List<string>("B1", "B2");
            socialNetworkService.GetFriendsOfFriends_Expected =
                Utils.List<string>("C1");

            locationService.CurrentLocations = Utils.Map<string, UserInfo>(
                "me", new UserInfo { FacebookUserId = "me", Location = new LatLong(0, 0) },
                "B1", new UserInfo { FacebookUserId = "B1", Location = new LatLong(0, 2) },
                "B2", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 1) },
                "C1", new UserInfo { FacebookUserId = "B2", Location = new LatLong(0, 3) }
            );

            usersService.Preferences = Utils.Map<string, UserPreference>(
                "me", new UserPreference { FacebookUserId = "me", NearbyRadiusKM = 0, VisibilityLevel = (int)VisibilityLevel.Everyone },
                "B1", new UserPreference { FacebookUserId = "B1", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
                "B2", new UserPreference { FacebookUserId = "B2", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone },
                "B3", new UserPreference { FacebookUserId = "B3", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone }
            );

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetAllPeople("me"));
            Assert.AreEqual(3, persons.Count);
            Assert.AreEqual(null, persons.Find(delegate(PersonNearby pn) { return pn.lastLocationUpdate == null; }));
        }
	}
}
